package com.zouxw.utils.json.model;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zouxw.utils.json.utils.JsonParseException;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

/**
 * JSON数据模型类
 * 负责管理JSON数据的解析、验证和操作
 * 使用观察者模式通知视图更新
 * 
 * @author zouxw
 * @version 1.0
 */
public class JsonModel extends Observable {
    
    // ==================== 实例变量 ====================
    /** 根JSON对象 */
    private Object rootJsonObject;
    
    /** 原始JSON字符串 */
    private String originalJsonString;
    
    /** 当前JSON字符串 */
    private String currentJsonString;
    
    /** 是否已修改 */
    private boolean modified = false;
    
    /** 验证状态 */
    private ValidationStatus validationStatus = ValidationStatus.UNKNOWN;
    
    /** 验证错误消息 */
    private String validationErrorMessage;
    
    // ==================== 验证状态枚举 ====================
    public enum ValidationStatus {
        /** 未知状态 */
        UNKNOWN,
        /** 验证中 */
        VALIDATING,
        /** 验证通过 */
        VALID,
        /** 验证失败 */
        INVALID,
        /** 空内容 */
        EMPTY
    }
    
    // ==================== 构造函数 ====================
    
    /**
     * 默认构造函数
     */
    public JsonModel() {
        // 空构造函数
    }
    
    // ==================== 公共方法 ====================
    
    /**
     * 解析JSON字符串
     * 
     * @param jsonString JSON字符串
     * @throws JsonParseException 解析异常
     */
    public void parseJson(String jsonString) throws JsonParseException {
        if (jsonString == null) {
            throw new JsonParseException("JSON字符串不能为null", JsonParseException.ErrorType.FORMAT_ERROR);
        }
        
        String trimmedJson = jsonString.trim();
        
        if (trimmedJson.isEmpty()) {
            setValidationStatus(ValidationStatus.EMPTY);
            setOriginalJsonString("");
            setCurrentJsonString("");
            setRootJsonObject(null);
            setModified(false);
            notifyModelChanged();
            return;
        }
        
        try {
            setValidationStatus(ValidationStatus.VALIDATING);
            notifyModelChanged();
            
            Object parsedObject = JSON.parse(trimmedJson);
            setRootJsonObject(parsedObject);
            setOriginalJsonString(trimmedJson);
            setCurrentJsonString(trimmedJson);
            setValidationStatus(ValidationStatus.VALID);
            setValidationErrorMessage(null);
            setModified(false);
            
            notifyModelChanged();
            
        } catch (Exception e) {
            setValidationStatus(ValidationStatus.INVALID);
            setValidationErrorMessage(e.getMessage());
            throw new JsonParseException("JSON解析失败: " + e.getMessage(), 
                    JsonParseException.ErrorType.FORMAT_ERROR, e);
        }
    }
    
    /**
     * 验证JSON字符串
     * 
     * @param jsonString JSON字符串
     * @return 验证状态
     */
    public ValidationStatus validateJson(String jsonString) {
        if (jsonString == null || jsonString.trim().isEmpty()) {
            setValidationStatus(ValidationStatus.EMPTY);
            setValidationErrorMessage(null);
            return ValidationStatus.EMPTY;
        }
        
        try {
            JSON.parse(jsonString.trim());
            setValidationStatus(ValidationStatus.VALID);
            setValidationErrorMessage(null);
            return ValidationStatus.VALID;
        } catch (Exception e) {
            setValidationStatus(ValidationStatus.INVALID);
            setValidationErrorMessage(e.getMessage());
            return ValidationStatus.INVALID;
        }
    }
    
    /**
     * 格式化JSON
     * 
     * @param pretty 是否美化格式
     * @throws JsonParseException 解析异常
     */
    public void formatJson(boolean pretty) throws JsonParseException {
        if (rootJsonObject == null) {
            throw new JsonParseException("没有可格式化的JSON数据", JsonParseException.ErrorType.STRUCTURE_ERROR);
        }
        
        try {
            String formattedJson = pretty ? 
                    JSON.toJSONString(rootJsonObject, true) : 
                    JSON.toJSONString(rootJsonObject);
            
            setCurrentJsonString(formattedJson);
            setModified(true);
            notifyObservers();
            
        } catch (Exception e) {
            throw new JsonParseException("JSON格式化失败: " + e.getMessage(), 
                    JsonParseException.ErrorType.STRUCTURE_ERROR, e);
        }
    }
    
    /**
     * 更新节点值
     * 
     * @param nodePath 节点路径
     * @param newValue 新值
     * @throws JsonParseException 更新异常
     */
    public void updateNodeValue(String nodePath, Object newValue) throws JsonParseException {
        if (rootJsonObject == null) {
            throw new JsonParseException("没有可更新的JSON数据", JsonParseException.ErrorType.STRUCTURE_ERROR);
        }
        
        try {
            // 这里需要实现路径解析和值更新逻辑
            // 暂时简化实现
            setModified(true);
            notifyObservers();
            
        } catch (Exception e) {
            throw new JsonParseException("更新节点值失败: " + e.getMessage(), 
                    JsonParseException.ErrorType.STRUCTURE_ERROR, e);
        }
    }
    
    /**
     * 添加新属性
     * 
     * @param parentPath 父节点路径
     * @param key 键名
     * @param value 值
     * @throws JsonParseException 添加异常
     */
    public void addProperty(String parentPath, String key, Object value) throws JsonParseException {
        if (rootJsonObject == null) {
            throw new JsonParseException("没有可操作的JSON数据", JsonParseException.ErrorType.STRUCTURE_ERROR);
        }
        
        try {
            // 这里需要实现属性添加逻辑
            setModified(true);
            notifyObservers();
            
        } catch (Exception e) {
            throw new JsonParseException("添加属性失败: " + e.getMessage(), 
                    JsonParseException.ErrorType.STRUCTURE_ERROR, e);
        }
    }
    
    /**
     * 添加数组元素
     * 
     * @param parentPath 父节点路径
     * @param value 值
     * @throws JsonParseException 添加异常
     */
    public void addArrayElement(String parentPath, Object value) throws JsonParseException {
        if (rootJsonObject == null) {
            throw new JsonParseException("没有可操作的JSON数据", JsonParseException.ErrorType.STRUCTURE_ERROR);
        }
        
        try {
            // 这里需要实现数组元素添加逻辑
            setModified(true);
            notifyObservers();
            
        } catch (Exception e) {
            throw new JsonParseException("添加数组元素失败: " + e.getMessage(), 
                    JsonParseException.ErrorType.STRUCTURE_ERROR, e);
        }
    }
    
    /**
     * 删除节点
     * 
     * @param nodePath 节点路径
     * @throws JsonParseException 删除异常
     */
    public void deleteNode(String nodePath) throws JsonParseException {
        if (rootJsonObject == null) {
            throw new JsonParseException("没有可操作的JSON数据", JsonParseException.ErrorType.STRUCTURE_ERROR);
        }
        
        try {
            // 这里需要实现节点删除逻辑
            setModified(true);
            notifyObservers();
            
        } catch (Exception e) {
            throw new JsonParseException("删除节点失败: " + e.getMessage(), 
                    JsonParseException.ErrorType.STRUCTURE_ERROR, e);
        }
    }
    
    /**
     * 重置模型
     */
    public void reset() {
        setRootJsonObject(null);
        setOriginalJsonString("");
        setCurrentJsonString("");
        setModified(false);
        setValidationStatus(ValidationStatus.UNKNOWN);
        setValidationErrorMessage(null);
        notifyObservers();
    }
    
    /**
     * 获取JSON统计信息
     * 
     * @return 统计信息
     */
    public JsonStatistics getStatistics() {
        if (rootJsonObject == null) {
            return new JsonStatistics();
        }
        
        return calculateStatistics(rootJsonObject);
    }
    
    // ==================== Getter和Setter方法 ====================
    
    /**
     * 获取根JSON对象
     * 
     * @return 根JSON对象
     */
    public Object getRootJsonObject() {
        return rootJsonObject;
    }
    
    /**
     * 设置根JSON对象
     * 
     * @param rootJsonObject 根JSON对象
     */
    private void setRootJsonObject(Object rootJsonObject) {
        this.rootJsonObject = rootJsonObject;
    }
    
    /**
     * 获取原始JSON字符串
     * 
     * @return 原始JSON字符串
     */
    public String getOriginalJsonString() {
        return originalJsonString;
    }
    
    /**
     * 设置原始JSON字符串
     * 
     * @param originalJsonString 原始JSON字符串
     */
    private void setOriginalJsonString(String originalJsonString) {
        this.originalJsonString = originalJsonString;
    }
    
    /**
     * 获取当前JSON字符串
     * 
     * @return 当前JSON字符串
     */
    public String getCurrentJsonString() {
        return currentJsonString;
    }
    
    /**
     * 设置当前JSON字符串
     * 
     * @param currentJsonString 当前JSON字符串
     */
    private void setCurrentJsonString(String currentJsonString) {
        this.currentJsonString = currentJsonString;
    }
    
    /**
     * 是否已修改
     * 
     * @return 是否已修改
     */
    public boolean isModified() {
        return modified;
    }
    
    /**
     * 设置修改状态
     * 
     * @param modified 是否已修改
     */
    private void setModified(boolean modified) {
        this.modified = modified;
    }
    
    /**
     * 获取验证状态
     * 
     * @return 验证状态
     */
    public ValidationStatus getValidationStatus() {
        return validationStatus;
    }
    
    /**
     * 设置验证状态
     * 
     * @param validationStatus 验证状态
     */
    private void setValidationStatus(ValidationStatus validationStatus) {
        this.validationStatus = validationStatus;
    }
    
    /**
     * 获取验证错误消息
     * 
     * @return 验证错误消息
     */
    public String getValidationErrorMessage() {
        return validationErrorMessage;
    }
    
    /**
     * 设置验证错误消息
     * 
     * @param validationErrorMessage 验证错误消息
     */
    private void setValidationErrorMessage(String validationErrorMessage) {
        this.validationErrorMessage = validationErrorMessage;
    }
    
    // ==================== 私有辅助方法 ====================
    
    /**
     * 通知观察者模型已更改
     */
    private void notifyModelChanged() {
        setChanged();
        notifyObservers();
    }
    
    /**
     * 计算JSON统计信息
     * 
     * @param jsonObject JSON对象
     * @return 统计信息
     */
    private JsonStatistics calculateStatistics(Object jsonObject) {
        JsonStatistics stats = new JsonStatistics();
        calculateStatisticsRecursive(jsonObject, stats);
        return stats;
    }
    
    /**
     * 递归计算统计信息
     * 
     * @param obj 对象
     * @param stats 统计信息
     */
    private void calculateStatisticsRecursive(Object obj, JsonStatistics stats) {
        if (obj instanceof JSONObject) {
            JSONObject jsonObj = (JSONObject) obj;
            stats.incrementObjectCount();
            for (Object value : jsonObj.values()) {
                calculateStatisticsRecursive(value, stats);
            }
        } else if (obj instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) obj;
            stats.incrementArrayCount();
            for (Object item : jsonArray) {
                calculateStatisticsRecursive(item, stats);
            }
        } else {
            stats.incrementPrimitiveCount();
        }
    }
    
    // ==================== 内部类 ====================
    
    /**
     * JSON统计信息类
     */
    public static class JsonStatistics {
        private int objectCount = 0;
        private int arrayCount = 0;
        private int primitiveCount = 0;
        
        public void incrementObjectCount() { objectCount++; }
        public void incrementArrayCount() { arrayCount++; }
        public void incrementPrimitiveCount() { primitiveCount++; }
        
        public int getObjectCount() { return objectCount; }
        public int getArrayCount() { return arrayCount; }
        public int getPrimitiveCount() { return primitiveCount; }
        public int getTotalCount() { return objectCount + arrayCount + primitiveCount; }
        
        @Override
        public String toString() {
            return String.format("对象: %d, 数组: %d, 基本值: %d, 总计: %d", 
                    objectCount, arrayCount, primitiveCount, getTotalCount());
        }
    }
}
